1   /*                        __    __  __  __    __  ___
2    *                       \  \  /  /    \  \  /  /  __/
3    *                        \  \/  /  /\  \  \/  /  /
4    *                         \____/__/  \__\____/__/.ɪᴏ
5    * ᶜᵒᵖʸʳᶦᵍʰᵗ ᵇʸ ᵛᵃᵛʳ ⁻ ˡᶦᶜᵉⁿˢᵉᵈ ᵘⁿᵈᵉʳ ᵗʰᵉ ᵃᵖᵃᶜʰᵉ ˡᶦᶜᵉⁿˢᵉ ᵛᵉʳˢᶦᵒⁿ ᵗʷᵒ ᵈᵒᵗ ᶻᵉʳᵒ
6    */
7   package io.vavr.collection;
8   
9   import io.vavr.Tuple;
10  import io.vavr.Tuple2;
11  import io.vavr.Tuple3;
12  import io.vavr.collection.RedBlackTreeModule.Empty;
13  import io.vavr.collection.RedBlackTreeModule.Node;
14  import io.vavr.control.Option;
15  
16  import java.io.Serializable;
17  import java.util.Comparator;
18  import java.util.NoSuchElementException;
19  import java.util.Objects;
20  
21  import static io.vavr.collection.RedBlackTree.Color.BLACK;
22  import static io.vavr.collection.RedBlackTree.Color.RED;
23  
24  /**
25   * Purely functional Red/Black Tree, inspired by <a href="https://github.com/kazu-yamamoto/llrbtree/blob/master/Data/Set/RBTree.hs">Kazu Yamamoto's Haskell implementation</a>.
26   * <p>
27   * Based on
28   * <ul>
29   * <li><a href="http://www.eecs.usma.edu/webs/people/okasaki/pubs.html#jfp99">Chris Okasaki, "Red-Black Trees in a Functional Setting", Journal of Functional Programming, 9(4), pp 471-477, July 1999</a></li>
30   * <li>Stefan Kahrs, "Red-black trees with types", Journal of functional programming, 11(04), pp 425-432, July 2001</li>
31   * </ul>
32   *
33   * @param <T> Component type
34   * @author Daniel Dietrich
35   */
36  interface RedBlackTree<T> extends Iterable<T> {
37  
38      static <T extends Comparable<? super T>> RedBlackTree<T> empty() {
39          return new Empty<>(Comparators.naturalComparator());
40      }
41  
42      static <T> RedBlackTree<T> empty(Comparator<? super T> comparator) {
43          Objects.requireNonNull(comparator, "comparator is null");
44          return new Empty<>(comparator);
45      }
46  
47      static <T extends Comparable<? super T>> RedBlackTree<T> of(T value) {
48          return of(Comparators.naturalComparator(), value);
49      }
50  
51      static <T> RedBlackTree<T> of(Comparator<? super T> comparator, T value) {
52          Objects.requireNonNull(comparator, "comparator is null");
53          final Empty<T> empty = new Empty<>(comparator);
54          return new Node<>(BLACK, 1, empty, value, empty, empty);
55      }
56  
57      @SuppressWarnings("varargs")
58      @SafeVarargs
59      static <T extends Comparable<? super T>> RedBlackTree<T> of(T... values) {
60          Objects.requireNonNull(values, "values is null");
61          return of(Comparators.<T> naturalComparator(), values);
62      }
63  
64      @SafeVarargs
65      static <T> RedBlackTree<T> of(Comparator<? super T> comparator, T... values) {
66          Objects.requireNonNull(comparator, "comparator is null");
67          Objects.requireNonNull(values, "values is null");
68          RedBlackTree<T> tree = empty(comparator);
69          for (T value : values) {
70              tree = tree.insert(value);
71          }
72          return tree;
73      }
74  
75      static <T extends Comparable<? super T>> RedBlackTree<T> ofAll(Iterable<? extends T> values) {
76          Objects.requireNonNull(values, "values is null");
77          return ofAll(Comparators.naturalComparator(), values);
78      }
79  
80      @SuppressWarnings("unchecked")
81      static <T> RedBlackTree<T> ofAll(Comparator<? super T> comparator, Iterable<? extends T> values) {
82          Objects.requireNonNull(comparator, "comparator is null");
83          Objects.requireNonNull(values, "values is null");
84          // function equality is not computable => same object check
85          if (values instanceof RedBlackTree && ((RedBlackTree<T>) values).comparator() == comparator) {
86              return (RedBlackTree<T>) values;
87          } else {
88              RedBlackTree<T> tree = empty(comparator);
89              for (T value : values) {
90                  tree = tree.insert(value);
91              }
92              return tree;
93          }
94      }
95  
96      /**
97       * Inserts a new value into this tree.
98       *
99       * @param value A value.
100      * @return A new tree if this tree does not contain the given value, otherwise the same tree instance.
101      */
102     default RedBlackTree<T> insert(T value) {
103         return Node.insert(this, value).color(BLACK);
104     }
105 
106     /**
107      * Return the {@link Color} of this Red/Black Tree node.
108      * <p>
109      * An empty node is {@code BLACK} by definition.
110      *
111      * @return Either {@code RED} or {@code BLACK}.
112      */
113     Color color();
114 
115     /**
116      * Returns the underlying {@link java.util.Comparator} of this RedBlackTree.
117      *
118      * @return The comparator.
119      */
120     Comparator<T> comparator();
121 
122     /**
123      * Checks, if this {@code RedBlackTree} contains the given {@code value}.
124      *
125      * @param value A value.
126      * @return true, if this tree contains the value, false otherwise.
127      */
128     boolean contains(T value);
129 
130     /**
131      * Deletes a value from this RedBlackTree.
132      *
133      * @param value A value
134      * @return A new RedBlackTree if the value is present, otherwise this.
135      */
136     default RedBlackTree<T> delete(T value) {
137         final RedBlackTree<T> tree = Node.delete(this, value)._1;
138         return Node.color(tree, BLACK);
139     }
140 
141     default RedBlackTree<T> difference(RedBlackTree<T> tree) {
142         Objects.requireNonNull(tree, "tree is null");
143         if (isEmpty() || tree.isEmpty()) {
144             return this;
145         } else {
146             final Node<T> that = (Node<T>) tree;
147             final Tuple2<RedBlackTree<T>, RedBlackTree<T>> split = Node.split(this, that.value);
148             return Node.merge(split._1.difference(that.left), split._2.difference(that.right));
149         }
150     }
151 
152     /**
153      * Returns the empty instance of this RedBlackTree.
154      *
155      * @return An empty ReadBlackTree
156      */
157     RedBlackTree<T> emptyInstance();
158 
159     /**
160      * Finds the value stored in this tree, if exists, by applying the underlying comparator to the tree elements and
161      * the given element.
162      * <p>
163      * Especially the value returned may differ from the given value, even if the underlying comparator states that
164      * both are equal.
165      *
166      * @param value A value
167      * @return Some value, if this tree contains a value equal to the given value according to the underlying comparator. Otherwise None.
168      */
169     Option<T> find(T value);
170 
171     default RedBlackTree<T> intersection(RedBlackTree<T> tree) {
172         Objects.requireNonNull(tree, "tree is null");
173         if (isEmpty()) {
174             return this;
175         } else if (tree.isEmpty()) {
176             return tree;
177         } else {
178             final Node<T> that = (Node<T>) tree;
179             final Tuple2<RedBlackTree<T>, RedBlackTree<T>> split = Node.split(this, that.value);
180             if (contains(that.value)) {
181                 return Node.join(split._1.intersection(that.left), that.value, split._2.intersection(that.right));
182             } else {
183                 return Node.merge(split._1.intersection(that.left), split._2.intersection(that.right));
184             }
185         }
186     }
187 
188     /**
189      * Checks if this {@code RedBlackTree} is empty, i.e. an instance of {@code Leaf}.
190      *
191      * @return true, if it is empty, false otherwise.
192      */
193     boolean isEmpty();
194 
195     /**
196      * Returns the left child if this is a non-empty node, otherwise throws.
197      *
198      * @return The left child.
199      * @throws UnsupportedOperationException if this RedBlackTree is empty
200      */
201     RedBlackTree<T> left();
202 
203     /**
204      * Returns the maximum element of this tree according to the underlying comparator.
205      *
206      * @return Some element, if this is not empty, otherwise None
207      */
208     default Option<T> max() {
209         return isEmpty() ? Option.none() : Option.some(Node.maximum((Node<T>) this));
210     }
211 
212     /**
213      * Returns the minimum element of this tree according to the underlying comparator.
214      *
215      * @return Some element, if this is not empty, otherwise None
216      */
217     default Option<T> min() {
218         return isEmpty() ? Option.none() : Option.some(Node.minimum((Node<T>) this));
219     }
220 
221     /**
222      * Returns the right child if this is a non-empty node, otherwise throws.
223      *
224      * @return The right child.
225      * @throws UnsupportedOperationException if this RedBlackTree is empty
226      */
227     RedBlackTree<T> right();
228 
229     /**
230      * Returns the size of this tree.
231      *
232      * @return the number of nodes of this tree and 0 if this is the empty tree
233      */
234     int size();
235 
236     /**
237      * Adds all of the elements of the given {@code tree} to this tree, if not already present.
238      *
239      * @param tree The RedBlackTree to form the union with.
240      * @return A new RedBlackTree that contains all distinct elements of this and the given {@code tree}.
241      */
242     default RedBlackTree<T> union(RedBlackTree<T> tree) {
243         Objects.requireNonNull(tree, "tree is null");
244         if (tree.isEmpty()) {
245             return this;
246         } else {
247             final Node<T> that = (Node<T>) tree;
248             if (isEmpty()) {
249                 return that.color(BLACK);
250             } else {
251                 final Tuple2<RedBlackTree<T>, RedBlackTree<T>> split = Node.split(this, that.value);
252                 return Node.join(split._1.union(that.left), that.value, split._2.union(that.right));
253             }
254         }
255     }
256 
257     /**
258      * Returns the value of the current tree node or throws if this is empty.
259      *
260      * @return The value.
261      * @throws NoSuchElementException if this is the empty node.
262      */
263     T value();
264 
265     /**
266      * Returns an Iterator that iterates elements in the order induced by the underlying Comparator.
267      * <p>
268      * Internally an in-order traversal of the RedBlackTree is performed.
269      * <p>
270      * Example:
271      *
272      * <pre><code>
273      *       4
274      *      / \
275      *     2   6
276      *    / \ / \
277      *   1  3 5  7
278      * </code></pre>
279      *
280      * Iteration order: 1, 2, 3, 4, 5, 6, 7
281      * <p>
282      * See also <a href="http://n00tc0d3r.blogspot.de/2013/08/implement-iterator-for-binarytree-i-in.html">Implement Iterator for BinaryTree I (In-order)</a>.
283      */
284     @Override
285     default Iterator<T> iterator() {
286         if (isEmpty()) {
287             return Iterator.empty();
288         } else {
289             final Node<T> that = (Node<T>) this;
290             return new AbstractIterator<T>() {
291 
292                 List<Node<T>> stack = pushLeftChildren(List.empty(), that);
293 
294                 @Override
295                 public boolean hasNext() {
296                     return !stack.isEmpty();
297                 }
298 
299                 @Override
300                 public T getNext() {
301                     final Tuple2<Node<T>, ? extends List<Node<T>>> result = stack.pop2();
302                     final Node<T> node = result._1;
303                     stack = node.right.isEmpty() ? result._2 : pushLeftChildren(result._2, (Node<T>) node.right);
304                     return result._1.value;
305                 }
306 
307                 private List<Node<T>> pushLeftChildren(List<Node<T>> initialStack, Node<T> that) {
308                     List<Node<T>> stack = initialStack;
309                     RedBlackTree<T> tree = that;
310                     while (!tree.isEmpty()) {
311                         final Node<T> node = (Node<T>) tree;
312                         stack = stack.push(node);
313                         tree = node.left;
314                     }
315                     return stack;
316                 }
317             };
318         }
319     }
320 
321     /**
322      * Compares color, value and sub-trees. The comparator is not compared because function equality is not computable.
323      *
324      * @return The hash code of this tree.
325      */
326     @Override
327     boolean equals(Object o);
328 
329     /**
330      * Computes the hash code of this tree based on color, value and sub-trees. The comparator is not taken into account.
331      *
332      * @return The hash code of this tree.
333      */
334     @Override
335     int hashCode();
336 
337     /**
338      * Returns a Lisp like representation of this tree.
339      *
340      * @return This Tree as Lisp like String.
341      */
342     @Override
343     String toString();
344 
345     enum Color {
346 
347         RED, BLACK;
348 
349         @Override
350         public String toString() {
351             return (this == RED) ? "R" : "B";
352         }
353     }
354 }
355 
356 interface RedBlackTreeModule {
357 
358     /**
359      * A non-empty tree node.
360      *
361      * @param <T> Component type
362      */
363     final class Node<T> implements RedBlackTree<T>, Serializable {
364 
365         private static final long serialVersionUID = 1L;
366 
367         final Color color;
368         final int blackHeight;
369         final RedBlackTree<T> left;
370         final T value;
371         final RedBlackTree<T> right;
372         final Empty<T> empty;
373         final int size;
374 
375         // This is no public API! The RedBlackTree takes care of passing the correct Comparator.
376         Node(Color color, int blackHeight, RedBlackTree<T> left, T value, RedBlackTree<T> right, Empty<T> empty) {
377             this.color = color;
378             this.blackHeight = blackHeight;
379             this.left = left;
380             this.value = value;
381             this.right = right;
382             this.empty = empty;
383             this.size = left.size() + right.size() + 1;
384         }
385 
386         @Override
387         public Color color() {
388             return color;
389         }
390 
391         @Override
392         public Comparator<T> comparator() {
393             return empty.comparator;
394         }
395 
396         @Override
397         public boolean contains(T value) {
398             final int result = empty.comparator.compare(value, this.value);
399             if (result < 0) {
400                 return left.contains(value);
401             } else if (result > 0) {
402                 return right.contains(value);
403             } else {
404                 return true;
405             }
406         }
407 
408         @Override
409         public Empty<T> emptyInstance() {
410             return empty;
411         }
412 
413         @Override
414         public Option<T> find(T value) {
415             final int result = empty.comparator.compare(value, this.value);
416             if (result < 0) {
417                 return left.find(value);
418             } else if (result > 0) {
419                 return right.find(value);
420             } else {
421                 return Option.some(this.value);
422             }
423         }
424 
425         @Override
426         public boolean isEmpty() {
427             return false;
428         }
429 
430         @Override
431         public RedBlackTree<T> left() {
432             return left;
433         }
434 
435         @Override
436         public RedBlackTree<T> right() {
437             return right;
438         }
439 
440         @Override
441         public int size() {
442             return size;
443         }
444 
445         @Override
446         public T value() {
447             return value;
448         }
449 
450         @Override
451         public boolean equals(Object o) {
452             if (o == this) {
453                 return true;
454             } else if (o instanceof Node) {
455                 final Node<?> that = (Node<?>) o;
456                 return Collections.areEqual(this, that);
457             } else {
458                 return false;
459             }
460         }
461 
462         @Override
463         public int hashCode() {
464             // DEV-NOTE: Using `Objects.hash(this.value, this.left, this.right)` would leak the tree structure to the outside.
465             //           We just want to hash the values in the right order.
466             return Collections.hashOrdered(this);
467         }
468 
469         @Override
470         public String toString() {
471             return isLeaf() ? "(" + color + ":" + value + ")" : toLispString(this);
472         }
473 
474         private static String toLispString(RedBlackTree<?> tree) {
475             if (tree.isEmpty()) {
476                 return "";
477             } else {
478                 final Node<?> node = (Node<?>) tree;
479                 final String value = node.color + ":" + node.value;
480                 if (node.isLeaf()) {
481                     return value;
482                 } else {
483                     final String left = node.left.isEmpty() ? "" : " " + toLispString(node.left);
484                     final String right = node.right.isEmpty() ? "" : " " + toLispString(node.right);
485                     return "(" + value + left + right + ")";
486                 }
487             }
488         }
489 
490         private boolean isLeaf() {
491             return left.isEmpty() && right.isEmpty();
492         }
493 
494         Node<T> color(Color color) {
495             return (this.color == color) ? this : new Node<>(color, blackHeight, left, value, right, empty);
496         }
497 
498         static <T> RedBlackTree<T> color(RedBlackTree<T> tree, Color color) {
499             return tree.isEmpty() ? tree : ((Node<T>) tree).color(color);
500         }
501 
502         private static <T> Node<T> balanceLeft(Color color, int blackHeight, RedBlackTree<T> left, T value,
503                 RedBlackTree<T> right, Empty<T> empty) {
504             if (color == BLACK) {
505                 if (!left.isEmpty()) {
506                     final Node<T> ln = (Node<T>) left;
507                     if (ln.color == RED) {
508                         if (!ln.left.isEmpty()) {
509                             final Node<T> lln = (Node<T>) ln.left;
510                             if (lln.color == RED) {
511                                 final Node<T> newLeft = new Node<>(BLACK, blackHeight, lln.left, lln.value, lln.right,
512                                         empty);
513                                 final Node<T> newRight = new Node<>(BLACK, blackHeight, ln.right, value, right, empty);
514                                 return new Node<>(RED, blackHeight + 1, newLeft, ln.value, newRight, empty);
515                             }
516                         }
517                         if (!ln.right.isEmpty()) {
518                             final Node<T> lrn = (Node<T>) ln.right;
519                             if (lrn.color == RED) {
520                                 final Node<T> newLeft = new Node<>(BLACK, blackHeight, ln.left, ln.value, lrn.left,
521                                         empty);
522                                 final Node<T> newRight = new Node<>(BLACK, blackHeight, lrn.right, value, right, empty);
523                                 return new Node<>(RED, blackHeight + 1, newLeft, lrn.value, newRight, empty);
524                             }
525                         }
526                     }
527                 }
528             }
529             return new Node<>(color, blackHeight, left, value, right, empty);
530         }
531 
532         private static <T> Node<T> balanceRight(Color color, int blackHeight, RedBlackTree<T> left, T value,
533                 RedBlackTree<T> right, Empty<T> empty) {
534             if (color == BLACK) {
535                 if (!right.isEmpty()) {
536                     final Node<T> rn = (Node<T>) right;
537                     if (rn.color == RED) {
538                         if (!rn.right.isEmpty()) {
539                             final Node<T> rrn = (Node<T>) rn.right;
540                             if (rrn.color == RED) {
541                                 final Node<T> newLeft = new Node<>(BLACK, blackHeight, left, value, rn.left, empty);
542                                 final Node<T> newRight = new Node<>(BLACK, blackHeight, rrn.left, rrn.value, rrn.right,
543                                         empty);
544                                 return new Node<>(RED, blackHeight + 1, newLeft, rn.value, newRight, empty);
545                             }
546                         }
547                         if (!rn.left.isEmpty()) {
548                             final Node<T> rln = (Node<T>) rn.left;
549                             if (rln.color == RED) {
550                                 final Node<T> newLeft = new Node<>(BLACK, blackHeight, left, value, rln.left, empty);
551                                 final Node<T> newRight = new Node<>(BLACK, blackHeight, rln.right, rn.value, rn.right,
552                                         empty);
553                                 return new Node<>(RED, blackHeight + 1, newLeft, rln.value, newRight, empty);
554                             }
555                         }
556                     }
557                 }
558             }
559             return new Node<>(color, blackHeight, left, value, right, empty);
560         }
561 
562         private static <T> Tuple2<? extends RedBlackTree<T>, Boolean> blackify(RedBlackTree<T> tree) {
563             if (tree instanceof Node) {
564                 final Node<T> node = (Node<T>) tree;
565                 if (node.color == RED) {
566                     return Tuple.of(node.color(BLACK), false);
567                 }
568             }
569             return Tuple.of(tree, true);
570         }
571 
572         static <T> Tuple2<? extends RedBlackTree<T>, Boolean> delete(RedBlackTree<T> tree, T value) {
573             if (tree.isEmpty()) {
574                 return Tuple.of(tree, false);
575             } else {
576                 final Node<T> node = (Node<T>) tree;
577                 final int comparison = node.comparator().compare(value, node.value);
578                 if (comparison < 0) {
579                     final Tuple2<? extends RedBlackTree<T>, Boolean> deleted = delete(node.left, value);
580                     final RedBlackTree<T> l = deleted._1;
581                     final boolean d = deleted._2;
582                     if (d) {
583                         return Node.unbalancedRight(node.color, node.blackHeight - 1, l, node.value, node.right,
584                                 node.empty);
585                     } else {
586                         final Node<T> newNode = new Node<>(node.color, node.blackHeight, l, node.value, node.right,
587                                 node.empty);
588                         return Tuple.of(newNode, false);
589                     }
590                 } else if (comparison > 0) {
591                     final Tuple2<? extends RedBlackTree<T>, Boolean> deleted = delete(node.right, value);
592                     final RedBlackTree<T> r = deleted._1;
593                     final boolean d = deleted._2;
594                     if (d) {
595                         return Node.unbalancedLeft(node.color, node.blackHeight - 1, node.left, node.value, r,
596                                 node.empty);
597                     } else {
598                         final Node<T> newNode = new Node<>(node.color, node.blackHeight, node.left, node.value, r,
599                                 node.empty);
600                         return Tuple.of(newNode, false);
601                     }
602                 } else {
603                     if (node.right.isEmpty()) {
604                         if (node.color == BLACK) {
605                             return blackify(node.left);
606                         } else {
607                             return Tuple.of(node.left, false);
608                         }
609                     } else {
610                         final Node<T> nodeRight = (Node<T>) node.right;
611                         final Tuple3<? extends RedBlackTree<T>, Boolean, T> newRight = deleteMin(nodeRight);
612                         final RedBlackTree<T> r = newRight._1;
613                         final boolean d = newRight._2;
614                         final T m = newRight._3;
615                         if (d) {
616                             return Node.unbalancedLeft(node.color, node.blackHeight - 1, node.left, m, r, node.empty);
617                         } else {
618                             final RedBlackTree<T> newNode = new Node<>(node.color, node.blackHeight, node.left, m, r,
619                                     node.empty);
620                             return Tuple.of(newNode, false);
621                         }
622                     }
623                 }
624             }
625         }
626 
627         private static <T> Tuple3<? extends RedBlackTree<T>, Boolean, T> deleteMin(Node<T> node) {
628             if (node.left.isEmpty()) {
629                 if (node.color == BLACK) {
630                     if (node.right.isEmpty()) {
631                         return Tuple.of(node.empty, true, node.value);
632                     } else {
633                         final Node<T> rightNode = (Node<T>) node.right;
634                         return Tuple.of(rightNode.color(BLACK), false, node.value);
635                     }
636                 } else {
637                     return Tuple.of(node.right, false, node.value);
638                 }
639             } else {
640                 final Node<T> nodeLeft = (Node<T>) node.left;
641                 final Tuple3<? extends RedBlackTree<T>, Boolean, T> newNode = deleteMin(nodeLeft);
642                 final RedBlackTree<T> l = newNode._1;
643                 final boolean d = newNode._2;
644                 final T m = newNode._3;
645                 if (d) {
646                     final Tuple2<Node<T>, Boolean> tD = Node.unbalancedRight(node.color, node.blackHeight - 1, l,
647                             node.value, node.right, node.empty);
648                     return Tuple.of(tD._1, tD._2, m);
649                 } else {
650                     final Node<T> tD = new Node<>(node.color, node.blackHeight, l, node.value, node.right, node.empty);
651                     return Tuple.of(tD, false, m);
652                 }
653             }
654         }
655 
656         static <T> Node<T> insert(RedBlackTree<T> tree, T value) {
657             if (tree.isEmpty()) {
658                 final Empty<T> empty = (Empty<T>) tree;
659                 return new Node<>(RED, 1, empty, value, empty, empty);
660             } else {
661                 final Node<T> node = (Node<T>) tree;
662                 final int comparison = node.comparator().compare(value, node.value);
663                 if (comparison < 0) {
664                     final Node<T> newLeft = insert(node.left, value);
665                     return (newLeft == node.left)
666                            ? node
667                            : Node.balanceLeft(node.color, node.blackHeight, newLeft, node.value, node.right,
668                             node.empty);
669                 } else if (comparison > 0) {
670                     final Node<T> newRight = insert(node.right, value);
671                     return (newRight == node.right)
672                            ? node
673                            : Node.balanceRight(node.color, node.blackHeight, node.left, node.value, newRight,
674                             node.empty);
675                 } else {
676                     // DEV-NOTE: Even if there is no _comparison_ difference, the object may not be _equal_.
677                     //           To save an equals() call, which may be expensive, we return a new instance.
678                     return new Node<>(node.color, node.blackHeight, node.left, value, node.right, node.empty);
679                 }
680             }
681         }
682 
683         private static boolean isRed(RedBlackTree<?> tree) {
684             return !tree.isEmpty() && ((Node<?>) tree).color == RED;
685         }
686 
687         static <T> RedBlackTree<T> join(RedBlackTree<T> t1, T value, RedBlackTree<T> t2) {
688             if (t1.isEmpty()) {
689                 return t2.insert(value);
690             } else if (t2.isEmpty()) {
691                 return t1.insert(value);
692             } else {
693                 final Node<T> n1 = (Node<T>) t1;
694                 final Node<T> n2 = (Node<T>) t2;
695                 final int comparison = n1.blackHeight - n2.blackHeight;
696                 if (comparison < 0) {
697                     return Node.joinLT(n1, value, n2, n1.blackHeight).color(BLACK);
698                 } else if (comparison > 0) {
699                     return Node.joinGT(n1, value, n2, n2.blackHeight).color(BLACK);
700                 } else {
701                     return new Node<>(BLACK, n1.blackHeight + 1, n1, value, n2, n1.empty);
702                 }
703             }
704         }
705 
706         private static <T> Node<T> joinGT(Node<T> n1, T value, Node<T> n2, int h2) {
707             if (n1.blackHeight == h2) {
708                 return new Node<>(RED, h2 + 1, n1, value, n2, n1.empty);
709             } else {
710                 final Node<T> node = joinGT((Node<T>) n1.right, value, n2, h2);
711                 return Node.balanceRight(n1.color, n1.blackHeight, n1.left, n1.value, node, n2.empty);
712             }
713         }
714 
715         private static <T> Node<T> joinLT(Node<T> n1, T value, Node<T> n2, int h1) {
716             if (n2.blackHeight == h1) {
717                 return new Node<>(RED, h1 + 1, n1, value, n2, n1.empty);
718             } else {
719                 final Node<T> node = joinLT(n1, value, (Node<T>) n2.left, h1);
720                 return Node.balanceLeft(n2.color, n2.blackHeight, node, n2.value, n2.right, n2.empty);
721             }
722         }
723 
724         static <T> RedBlackTree<T> merge(RedBlackTree<T> t1, RedBlackTree<T> t2) {
725             if (t1.isEmpty()) {
726                 return t2;
727             } else if (t2.isEmpty()) {
728                 return t1;
729             } else {
730                 final Node<T> n1 = (Node<T>) t1;
731                 final Node<T> n2 = (Node<T>) t2;
732                 final int comparison = n1.blackHeight - n2.blackHeight;
733                 if (comparison < 0) {
734                     final Node<T> node = Node.mergeLT(n1, n2, n1.blackHeight);
735                     return Node.color(node, BLACK);
736                 } else if (comparison > 0) {
737                     final Node<T> node = Node.mergeGT(n1, n2, n2.blackHeight);
738                     return Node.color(node, BLACK);
739                 } else {
740                     final Node<T> node = Node.mergeEQ(n1, n2);
741                     return Node.color(node, BLACK);
742                 }
743             }
744         }
745 
746         private static <T> Node<T> mergeEQ(Node<T> n1, Node<T> n2) {
747             final T m = Node.minimum(n2);
748             final RedBlackTree<T> t2 = Node.deleteMin(n2)._1;
749             final int h2 = t2.isEmpty() ? 0 : ((Node<T>) t2).blackHeight;
750             if (n1.blackHeight == h2) {
751                 return new Node<>(RED, n1.blackHeight + 1, n1, m, t2, n1.empty);
752             } else if (isRed(n1.left)) {
753                 final Node<T> node = new Node<>(BLACK, n1.blackHeight, n1.right, m, t2, n1.empty);
754                 return new Node<>(RED, n1.blackHeight, Node.color(n1.left, BLACK), n1.value, node, n1.empty);
755             } else if (isRed(n1.right)) {
756                 final RedBlackTree<T> rl = ((Node<T>) n1.right).left;
757                 final T rx = ((Node<T>) n1.right).value;
758                 final RedBlackTree<T> rr = ((Node<T>) n1.right).right;
759                 final Node<T> left = new Node<>(RED, n1.blackHeight, n1.left, n1.value, rl, n1.empty);
760                 final Node<T> right = new Node<>(RED, n1.blackHeight, rr, m, t2, n1.empty);
761                 return new Node<>(BLACK, n1.blackHeight, left, rx, right, n1.empty);
762             } else {
763                 return new Node<>(BLACK, n1.blackHeight, n1.color(RED), m, t2, n1.empty);
764             }
765         }
766 
767         private static <T> Node<T> mergeGT(Node<T> n1, Node<T> n2, int h2) {
768             if (n1.blackHeight == h2) {
769                 return Node.mergeEQ(n1, n2);
770             } else {
771                 final Node<T> node = Node.mergeGT((Node<T>) n1.right, n2, h2);
772                 return Node.balanceRight(n1.color, n1.blackHeight, n1.left, n1.value, node, n1.empty);
773             }
774         }
775 
776         private static <T> Node<T> mergeLT(Node<T> n1, Node<T> n2, int h1) {
777             if (n2.blackHeight == h1) {
778                 return Node.mergeEQ(n1, n2);
779             } else {
780                 final Node<T> node = Node.mergeLT(n1, (Node<T>) n2.left, h1);
781                 return Node.balanceLeft(n2.color, n2.blackHeight, node, n2.value, n2.right, n2.empty);
782             }
783         }
784 
785         static <T> T maximum(Node<T> node) {
786             Node<T> curr = node;
787             while (!curr.right.isEmpty()) {
788                 curr = (Node<T>) curr.right;
789             }
790             return curr.value;
791         }
792 
793         static <T> T minimum(Node<T> node) {
794             Node<T> curr = node;
795             while (!curr.left.isEmpty()) {
796                 curr = (Node<T>) curr.left;
797             }
798             return curr.value;
799         }
800 
801         static <T> Tuple2<RedBlackTree<T>, RedBlackTree<T>> split(RedBlackTree<T> tree, T value) {
802             if (tree.isEmpty()) {
803                 return Tuple.of(tree, tree);
804             } else {
805                 final Node<T> node = (Node<T>) tree;
806                 final int comparison = node.comparator().compare(value, node.value);
807                 if (comparison < 0) {
808                     final Tuple2<RedBlackTree<T>, RedBlackTree<T>> split = Node.split(node.left, value);
809                     return Tuple.of(split._1, Node.join(split._2, node.value, Node.color(node.right, BLACK)));
810                 } else if (comparison > 0) {
811                     final Tuple2<RedBlackTree<T>, RedBlackTree<T>> split = Node.split(node.right, value);
812                     return Tuple.of(Node.join(Node.color(node.left, BLACK), node.value, split._1), split._2);
813                 } else {
814                     return Tuple.of(Node.color(node.left, BLACK), Node.color(node.right, BLACK));
815                 }
816             }
817         }
818 
819         private static <T> Tuple2<Node<T>, Boolean> unbalancedLeft(Color color, int blackHeight, RedBlackTree<T> left,
820                 T value, RedBlackTree<T> right, Empty<T> empty) {
821             if (!left.isEmpty()) {
822                 final Node<T> ln = (Node<T>) left;
823                 if (ln.color == BLACK) {
824                     final Node<T> newNode = Node.balanceLeft(BLACK, blackHeight, ln.color(RED), value, right, empty);
825                     return Tuple.of(newNode, color == BLACK);
826                 } else if (color == BLACK && !ln.right.isEmpty()) {
827                     final Node<T> lrn = (Node<T>) ln.right;
828                     if (lrn.color == BLACK) {
829                         final Node<T> newRightNode = Node.balanceLeft(BLACK, blackHeight, lrn.color(RED), value, right,
830                                 empty);
831                         final Node<T> newNode = new Node<>(BLACK, ln.blackHeight, ln.left, ln.value, newRightNode,
832                                 empty);
833                         return Tuple.of(newNode, false);
834                     }
835                 }
836             }
837             throw new IllegalStateException("unbalancedLeft(" + color + ", " + blackHeight + ", " + left + ", " + value + ", " + right + ")");
838         }
839 
840         private static <T> Tuple2<Node<T>, Boolean> unbalancedRight(Color color, int blackHeight, RedBlackTree<T> left,
841                 T value, RedBlackTree<T> right, Empty<T> empty) {
842             if (!right.isEmpty()) {
843                 final Node<T> rn = (Node<T>) right;
844                 if (rn.color == BLACK) {
845                     final Node<T> newNode = Node.balanceRight(BLACK, blackHeight, left, value, rn.color(RED), empty);
846                     return Tuple.of(newNode, color == BLACK);
847                 } else if (color == BLACK && !rn.left.isEmpty()) {
848                     final Node<T> rln = (Node<T>) rn.left;
849                     if (rln.color == BLACK) {
850                         final Node<T> newLeftNode = Node.balanceRight(BLACK, blackHeight, left, value, rln.color(RED),
851                                 empty);
852                         final Node<T> newNode = new Node<>(BLACK, rn.blackHeight, newLeftNode, rn.value, rn.right,
853                                 empty);
854                         return Tuple.of(newNode, false);
855                     }
856                 }
857             }
858             throw new IllegalStateException("unbalancedRight(" + color + ", " + blackHeight + ", " + left + ", " + value + ", " + right + ")");
859         }
860     }
861 
862     /**
863      * The empty tree node. It can't be a singleton because it depends on a {@link Comparator}.
864      *
865      * @param <T> Component type
866      */
867     final class Empty<T> implements RedBlackTree<T>, Serializable {
868 
869         private static final long serialVersionUID = 1L;
870 
871         final Comparator<T> comparator;
872 
873         // This is no public API! The RedBlackTree takes care of passing the correct Comparator.
874         @SuppressWarnings("unchecked")
875         Empty(Comparator<? super T> comparator) {
876             this.comparator = (Comparator<T>) comparator;
877         }
878 
879         @Override
880         public Color color() {
881             return BLACK;
882         }
883 
884         @Override
885         public Comparator<T> comparator() {
886             return comparator;
887         }
888 
889         @Override
890         public boolean contains(T value) {
891             return false;
892         }
893 
894         @Override
895         public Empty<T> emptyInstance() {
896             return this;
897         }
898 
899         @Override
900         public Option<T> find(T value) {
901             return Option.none();
902         }
903 
904         @Override
905         public boolean isEmpty() {
906             return true;
907         }
908 
909         @Override
910         public RedBlackTree<T> left() {
911             throw new UnsupportedOperationException("left on empty");
912         }
913 
914         @Override
915         public RedBlackTree<T> right() {
916             throw new UnsupportedOperationException("right on empty");
917         }
918 
919         @Override
920         public int size() {
921             return 0;
922         }
923 
924         @Override
925         public T value() {
926             throw new NoSuchElementException("value on empty");
927         }
928 
929         @Override
930         public boolean equals(Object o) {
931             // note: it is not possible to compare the comparators because function equality is not computable
932             return (o == this) || (o instanceof Empty);
933         }
934 
935         @Override
936         public int hashCode() {
937             return 1;
938         }
939 
940         @Override
941         public String toString() {
942             return "()";
943         }
944     }
945 }